<script>
    import render from '@/assets/utils/render.js'
    import {trigger} from '@/components/DynamicForm/components/generator/config.js'

    import {Actioner, PROC_DEF, PROC_FORM, PROC_INST, PROC_TASK} from "@/api";
    import {getUrlParam} from "@/assets/utils";
    import {Message} from "element-ui";
    import FlowLine from './FlowLine';

    /**
     * 校验组织机构组件是否为空
     */
    const setFcOrgSelectRule = ( conf, ctx ) => {
        return {
            validator: (rule, value, callback) => {
                var count = 0
                var val = ctx[ctx.confGlobal.formModel][rule.field]
                conf.tabList.forEach(key => {
                    val && Array.isArray(val[key]) && (count += val[key].length)
                })
                callback(count ? undefined : new Error(`${conf.title}不能为空`))
            },
            trigger: trigger[conf.tag],
            type: 'object',
            required: true,
        }
    }
    /**
     * 收集表单必填项并组装成ElementUI表单校验得rules选项
     * 表格除外 表格自带校验
     */
    function buildRules ( conf, ctx ) {
        if ( conf.vModel === undefined ||  !trigger[conf.tag]) return
        const rules = []
        if ( conf.required ) {
            const type = Array.isArray( conf.defaultValue ) ? 'array' : undefined
            let message = Array.isArray( conf.defaultValue ) ? `请至少选择一个` : conf.placeholder
            if ( message === undefined ) message = `${conf.label}不能为空`
            conf.tag === 'fc-org-select'
                ? rules.push( setFcOrgSelectRule( conf, ctx ) )
                : rules.push( { required: true, type, message, trigger: trigger[conf.tag] } )
        }
        // 自定义正则匹配
        if ( conf.regList && Array.isArray( conf.regList ) ) {
            conf.regList.forEach( item => {
                if ( item.pattern ) {
                    rules.push( { pattern: eval( item.pattern ), message: item.message, trigger: trigger[conf.tag] } )
                }
            } )
        }
        ctx.rules[conf.vModel] = rules
    }


    var setData = (ctx, val, prop, init = false) => {
        if (!prop) return
        ctx.$set(ctx[ctx.confGlobal.formModel], prop, val)
    }

    var _isMounted = false // 收集默认值 渲染完成之后防止重复收集默认值

    const buildData = (ctx, value, prop) => setData(ctx, value, prop, true)

    const layouts = {
        colFormItem: function (conf,  h, ctx, isList = false,) {
            buildRules(conf, ctx)
            !_isMounted && buildData(ctx, conf.defaultValue, conf.vModel)
            //buildData(ctx, conf.defaultValue, conf.vModel)
            let labelWidth = ''
            if ( conf.labelWidth ) labelWidth = `${conf.labelWidth}px`
            if ( isList ) labelWidth = "0px"
            const required = ( !trigger[conf.tag] && conf.required ) || conf.tag === 'fc-org-select'
            const handleInput = val => {
                setData(ctx, val, conf.vModel)
                if (conf.tag === 'fc-org-select') {
                    /**
                     * 组织机构组件数据复杂
                     * async-validator不一定能准确捕获到数据变化
                     * 所以在这里手动校验一次
                     */
                    ctx.$refs[ctx.confGlobal.formRef].validateField(conf.vModel,()=>{ })
                }
            }
            let item =  <el-col span={conf.span}>
                <el-form-item
            label-width={labelWidth}
            label={isList ? '' : conf.label}
            prop={conf.vModel}>
                <render
            formData={ctx[ctx.confGlobal.formModel]}
            conf={conf}
            value={ctx[ctx.confGlobal.formModel][conf.vModel]}
            ref={conf.rowType === 'table' ? conf.vModel : undefined}
            onInput={handleInput}
            />
            </el-form-item>
            </el-col>

            if (isList) {
                var tableTitle = <el-col span={24} style="font-size: 14px;padding:6px 0px;margin-bottom: 4px;border-bottom: 1px solid #e5e5e5;">{conf.label}</el-col>
                return [tableTitle, item]
            }

            return conf.hidden ? null : item;
        },

        rowFormItem: function (conf, h, ctx) {
            if ( conf.rowType === 'table' ) {
                ctx.tableRefs[conf.vModel] = conf
                const param = {...conf, config: conf, formSize: ctx.confGlobal.size, labelWidth: `${conf.labelWidth || ctx.confGlobal.labelWidth}px`}
                return this.colFormItem( param, h, ctx, conf.type === 'list' )
            }
            buildRules(conf, ctx)
            const props = {
                type: conf.type === 'default' ? undefined : conf.type,
                justify: conf.type === 'default' ? undefined : conf.justify,
                align: conf.type === 'default' ? undefined : conf.align,
                gutter: typeof conf.gutter === 'number' ? conf.gutter : undefined,
            }
            let row = <el-col span={conf.span || 24}>
                <el-row {...{ props: props }}>
            { Array.isArray(conf.children) && conf.children.map( ( el ) => layouts[el.layout]( el, h, ctx ) ) }
        </el-row>
            </el-col>
            let divider
            if (conf.showDivider) {
                let explain
                if (conf.cmpType === 'custom' && conf.explain) {
                    explain = <el-tooltip effect="dark" content="组件说明" placement="top">
                        <i class="el-icon-info"
                    onClick={ctx.showExplain.bind(this, conf.explain, conf.label)}
                    style="margin-right: 8px; color: #E6A23C;cursor: pointer;">
                        </i>
                        </el-tooltip>
                }
                divider = <el-col span={24}>
                    <el-divider content-position="left" >{explain} {conf.label}</el-divider>
                </el-col>
                return [divider, row]
            }
            return row
        },
    }

    export default {
        data () {

            //var confGlobal = this.$route.params.formData || mockData.formData
            //Object.freeze(confGlobal)

            /*return {
              procdefId: procdefId,
              tableRefs: {},
              drawerTitle: '',
              drawerText: '',
              drawerVisible: false,
              containerWidth: 90,
              confGlobal,
              [confGlobal.formModel]: {},
              [confGlobal.formRules]: {}
            }*/

            return {

                procdefId: null,
                procdef: null,
                tableRefs: {},
                config: null,
                drawerTitle: '',
                drawerText: '',
                drawerVisible: false,
                containerWidth: 100,
                confGlobal: null,
                formData: {},
                rules: {},
                flowLine: null,
                orgCollection:{
                    dep: [],
                    role: [],
                    user: [],
                    position: []
                },

                flowLoading: false,

                /**
                 * 表单操作权限
                 */
                formOperatesType: {
                    HIDE: 0,
                    READ: 1,
                    EDIT: 2
                },
                formTypes: {
                    Online: {
                                "label": "在线设计",
                                "value": 0
                            },
                    Custom: {
                        "label": "定制表单",
                        "value": 1
                    }}
            }
        },
        components: {
            FlowLine
        },
        computed: {
            formIsValid() {

                var that = this;

                var formData_ = this.formData;

                var result = true;

                if(!that.config){
                    return false;
                }

                if(that.config.basicSetting.formType != that.formTypes.Online.value){//非在线设计的表单
                    result = true;

                    that.flowLoading = true;
                    PROC_DEF.flow_line({
                        procdefId: that.procdefId,
                        var: that.formData
                    }).then(function (result) {

                        that.flowLoading = false;

                        that.flowLine = result.data;
                    })

                    return result;
                }

                if(this.confGlobal == null) {

                    result = false;

                    return result;
                }

                const isTableValid = this.checkTableData();

                var form = this.$refs[this.confGlobal.formRef];

                if(!form) {

                    result = false;

                    return result;
                }

                form.validate(valid => {
                    if (!valid || !isTableValid) {
                        result = false;
                    }
                })

                if(result){

                    that.flowLoading = true;
                    PROC_DEF.flow_line({
                        procdefId: that.procdefId,
                        var: that.formData
                    }).then(function (result) {

                        that.flowLoading = false;

                        that.flowLine = result.data;
                    })
                }else{
                    that.flowLoading = false;
                }

                return result;
            }
        },
        created (){

            var that = this;

            console.info("created start")

            that.procdefId = getUrlParam("procdefId");

            if(that.procdefId){//首次发起流程

                PROC_DEF.get(this.procdefId).then(function (data) {

                    that.procdef = data.data;

                    that.config = JSON.parse(that.procdef.config);

                    if(that.config.basicSetting.formType == that.formTypes.Online.value) {//在线设计的表单

                        var formOperates = JSON.parse(that.procdef.config).processData.properties.formOperates;
                        var formOperatesMap = {};

                        for (var i = 0; i < formOperates.length; i++) {
                            formOperatesMap[formOperates[i].formId] = formOperates[i].formOperate;
                        }

                        if (that.procdef) {

                            var formData = JSON.parse(that.procdef.config).formData;

                            for (var i = 0; i < formData.fields.length; i++) {

                                if (formOperatesMap[formData.fields[i].formId] == that.formOperatesType.HIDE) {

                                    formData.fields[i].hidden = true;

                                } else if (formOperatesMap[formData.fields[i].formId] == that.formOperatesType.READ) {

                                    formData.fields[i].disabled = true;

                                } else if (formOperatesMap[formData.fields[i].formId] == that.formOperatesType.EDIT) {

                                }
                            }

                            that.confGlobal = formData;
                        }
                    }

                    console.info(that);
                });

            }

            setInterval(function () {
                /**
                 * iframe-宽高自适应显示
                 */
                const iframe = document.getElementById('formIframe');

                if(iframe){

                    var userAgent = navigator.userAgent;
                    var subdoc = iframe.contentDocument || iframe.contentWindow.document;
                    var subbody = subdoc.body;
                    var realHeight;
                    //谷歌浏览器特殊处理
                    if(userAgent.indexOf("Chrome") > -1){
                        realHeight = subdoc.documentElement.scrollHeight;
                    }
                    else{
                        realHeight = subbody.scrollHeight;
                    }

                    iframe.height = realHeight;
                }
            }, 1000);

            console.info("created end")
        },
        mounted(){
            _isMounted = true
        },
        methods: {

            /**
             * 预览上传文件
             */
            onPreview(file){

              console.info('file:' + file);

            },

            submitForm () {

                var that = this;

                if(that.config.basicSetting.formType == that.formTypes.Online.value){
                    that.submitOnlineForm();
                }else{
                    that.submitCustomForm();
                }
            },

            submitOnlineForm(){

                var that = this;

                const isTableValid = this.checkTableData()
                this.$refs[this.confGlobal.formRef].validate(valid => {
                    if(!valid) return
                    if (!isTableValid) return
                    /*this.$notify({
                      title: '表单数据',
                      message: '请在控制台中查看数据输出',
                      position: 'bottom-right'
                    });*/

                    var nodeList = JSON.parse(JSON.stringify(that.flowLine));
                    nodeList.shift();

                    var parms = {
                        procdefId: that.procdefId,
                        title: '',
                        flowVal: JSON.stringify(that.formData),
                        nodeList: JSON.stringify(nodeList)
                    }

                    PROC_INST.start(parms).then(function (data) {

                        if(data.code == "200"){
                            Message( {
                                showClose: true,
                                message: '提交成功!',
                                type: 'success',
                                duration: 2000
                            } );

                            setTimeout(function () {

                                try{
                                    top.Win.closeAll();
                                }catch (e) {
                                    window.close();
                                }

                            }, 1500)
                        }else{

                            Message( {
                                showClose: true,
                                message: data.msg ? data.msg : '提交失败,请稍后重试!',
                                type: 'warning',
                                duration: 2000
                            } );

                        }
                    });
                })
            },

            submitCustomForm(){

                var that = this;

                var iframe = window.document.getElementById("formIframe");

                if(!iframe.contentWindow.validateForm()) return;

                var flowVal = iframe.contentWindow.getData();

                var nodeList = JSON.parse(JSON.stringify(that.flowLine));
                nodeList.shift();

                var parms = {
                    procdefId: that.procdefId,
                    title: '',
                    flowVal: JSON.stringify(flowVal),
                    nodeList: JSON.stringify(nodeList)
                }

                PROC_INST.start(parms).then(function (data) {

                    if(data.code == "200"){
                        Message( {
                            showClose: true,
                            message: '提交成功!',
                            type: 'success',
                            duration: 2000
                        } );

                        setTimeout(function () {

                            try{
                                top.Win.closeAll();
                            }catch (e) {
                                window.close();
                            }

                        }, 1500)
                    }else{

                        Message( {
                            showClose: true,
                            message: data.msg ? data.msg : '提交失败,请稍后重试!',
                            type: 'warning',
                            duration: 2000
                        } );

                    }
                });
            },

            /*assignor (){

            },*/

            resetForm() {
                this.$refs[this.confGlobal.formRef].resetFields()
                this.resetTableData()
            },

            cancle(){
                try{
                    top.Win.closeAll();
                }catch (e) {
                    window.close();
                }
            },

            selectNextNodeActioner(backFun){
                backFun([], []);
            },

            resetTableData(){
                Object.keys(this.tableRefs).forEach(vModel => {
                    // 由于render.js返回的动态组件 所以动态组件相当于是render的子组件
                    const res = this.$refs[vModel]['$children'][0].reset()
                })
            },

            checkTableData () {
                let valid = true
                Object.keys(this.tableRefs).forEach(vModel => {
                    const res = this.$refs[vModel].$children[0].submit()  // 返回false或表单数据
                    res ? (this[this.confGlobal.formModel][vModel] = res) : (valid = false)
                })
                return valid
            },

            showExplain (explainText, title) {
                if(!explainText) return
                this.drawerTitle = title
                this.drawerText = explainText
                this.drawerVisible = true
            },

            buildDrawer (h) {
                var content = <pre style="padding-left: 1rem;">{this.drawerText}</pre>
                return h('el-drawer', {
                        props: {
                            title: this.drawerTitle + '说明',
                            visible: this.drawerVisible,
                        },
                        on: {
                            'update:visible': val => this.drawerVisible = val
                        }
                    },
                    [content])
            },

            buildForm (h) {


                var content = null;
                var formObject = {};

                if(this.config.basicSetting.formType == this.formTypes.Online.value){

                    let labelPosition = this.confGlobal.labelPosition || 'left'
                    content = this.confGlobal.fields.map(c => layouts[c.layout](c, h, this))
                    formObject = {
                        props: {
                            model: this[this.confGlobal.formModel],
                            rules: this[this.confGlobal.formRules],
                            size: this.confGlobal.size,
                            labelWidth: this.confGlobal.labelWidth + 'px',
                            labelPosition: this.confGlobal.labelPosition || undefined
                        },
                        ref: this.confGlobal.formRef
                    }
                }else{
                    var storageCache = localStorage.ND_FASTDP;

                    var src = this.config.basicSetting.flowForm + "?token=" + JSON.parse(storageCache)["token"];

                    console.info(src);

                    content = <iframe id="formIframe" src={src} scrolling="no" frameborder="0" style="width: 100%;"/>
                }

                var btns = '';

                if(!this.actionerId){
                    btns = <el-col span={24} class="operation-btn">
                                <el-form-item>
                                    <el-button onClick={this.cancle}>取消</el-button>
                                    <el-button type="primary" onClick={this.submitForm}>提交</el-button>
                                </el-form-item>
                           </el-col>
                }else{
                    btns = <el-col span={24} class="operation-btn">
                                <el-form-item>
                                    <el-button onClick={this.cancle}>关闭</el-button>
                                    <el-button type="warning" onClick={this.refuse}>拒绝</el-button>
                                    <el-button type="success" onClick={this.agree}>同意</el-button>
                                </el-form-item>
                            </el-col>
                }

                // <el-button type="primary" onClick={this.assignor}>委托</el-button>


                const title= (<h3 style="text-align: center;">{this.procdef ? this.procdef.name : ""}</h3>)

                // 因为使用jsx时  el-form 的 model 一直无法正确填充，故采用createElement直接渲染
                return h('el-form', formObject, [btns, title, content])
            },

            onOrgChange(data){

            },

            getSelectActionerTitle(){
                return "选择审批人"
            }
        },

        render (h) {

            var result = "";

            //gutter={this.confGlobal.gutter}

            if(this.config != null && this.config.basicSetting != null){

                if(this.formIsValid && this.flowLine != null){

                    result = (<div class="preview-container" style={'width:' + this.containerWidth + '%;'}>
                                <el-row style="padding: 2rem 2rem 0;">
                                {this.buildForm(h)}
                                </el-row>

                                <el-row style="padding: 0rem 2rem 0;">
                                    <el-divider content-position="left">流程</el-divider>
                                </el-row>

                                <el-row style="padding: 0rem 2rem 0;padding-bottom:60px;" v-loading={this.flowLoading}>
                                <flow-line flowLine={this.flowLine}></flow-line>
                                </el-row>

                            {this.buildDrawer(h)}
                        </div>)

                }else{

                    result = (<div class="preview-container" style={'width:' + this.containerWidth + '%;'}>

                                    <el-row style="padding: 2rem 2rem 0;">
                                         {this.buildForm(h)}
                                    </el-row>

                                    <el-row style="padding: 0rem 2rem 0;">
                                        <el-divider content-position="left">流程</el-divider>
                                    </el-row>

                                    <el-row style="padding: 0rem 2rem 0;padding-bottom:60px;" v-loading={this.flowLoading}>
                                        <el-alert   title="流程条件未满足请先填写申请单"
                                                    type="info"
                                                    center
                                                    show-icon>
                                        </el-alert>
                                    </el-row>

                                {this.buildDrawer(h)}
                            </div>)
                }

            }

            return  result;
        }
    }
</script>
<!--
 <style lang="stylus" scoped>
-->
<style lang="stylus">
    .preview-container
        // margin 3rem auto 1rem
        border-radius 6px
      //box-shadow 0 0 15px rgba(0, 0, 0, .1)

        .width-slider
            width  150px
            position absolute
            top 0
            right 2rem

    .showDivider.form-container {
        margin-bottom: 2rem;
    }

    .operation-btn{
        position: fixed;
        z-index: 890;
        min-height: 50px;
        line-height: 50px;
        height: 50px;
        border-top: 1px solid #eee;
        padding-left: 0px;
        padding-right: 0px;
        background-color: #FFF;
        position: fixed;
        bottom: 0px;
        left: 0px;
        right: 0px;
        text-align center;
    }

    .operation-btn {
        .el-form-item {
            margin-top: 6.5px !important;
        }

        .el-form-item__content {
            margin-left: 0px !important;
        }
    }

    .el-input-number{
        .el-input__inner{
            text-align left!important;
        }

        .el-input-number--medium{
            width: 100%!important;
        }
    }
</style>
